package com.logisticsrepair.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.logisticsrepair.customEntity.UserRolePermissionEntity;
import com.logisticsrepair.entity.UserEntity;
import com.logisticsrepair.entity.UserRoleEntity;
import com.logisticsrepair.entity.WorkerEntity;
import com.logisticsrepair.entity.RoleEntity;
import com.logisticsrepair.mapper.RoleMapper;
import com.logisticsrepair.mapper.UserRoleMapper;
import com.logisticsrepair.service.UserService;
import com.logisticsrepair.service.WorkerService;
import com.logisticsrepair.util.RedisUtil;
import com.logisticsrepair.util.stpInterface.StpInterfaceImpl;
import com.logisticsrepair.util.responseUtil.ResponseEnum;
import com.logisticsrepair.util.responseUtil.ResponseUtil;
import com.logisticsrepair.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.Jedis;
import cn.hutool.crypto.digest.DigestUtil;
import java.util.UUID;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/api")
public class LoginController {

    //========================微信登录静态常量========================
    //真实账号 -- 要服务号才可以，订阅号不行
    //public static final String appID = "";
    //public static final String appSecret = "";
    //测试账号
    public static final String USER_TOKEN = "2RDfF9hhcQPqKp";
    public static final String appID = "wx09ba05658e0b3d08";
    public static final String appSecret = "de1122447ea17c80b0eb894ab7210576";
    public static final String REDIRECT_URI = "http://smallhairs.fgimaxl2.vipnps.vip/wx/respAuth1";
    //public static final String REDIRECT_URI = "http://smallhairrs.5gzvip.91tunnel.com/wx/respAuth";

    //========================自定义静态常量========================

    public static HashMap<Integer, String> err_oauth_code = new HashMap<>();
    public static HashMap<String, String> loginType = new HashMap();
    public static Jedis redis;
    public static String ADD_WORKER_PREFIX = "add_worker:";

    static {
        //非自定义的errcode，这是微信定义的，一般就用得到这些
        err_oauth_code.put(40029, "验证码无效");
        err_oauth_code.put(40163, "验证码已使用");
        err_oauth_code.put(41008, "验证码缺失");
        err_oauth_code.put(42003, "验证码超时");
        err_oauth_code.put(42009, "设置新身份");

        loginType.put("user", "wx:loginType:user");
        loginType.put("worker", "wx:loginType:worker");

        redis = RedisUtil.getRedis();
    }


    @Autowired
    UserService userService;

    @Autowired
    WorkerService workerService;

    @Autowired
    UserRoleMapper userRoleMapper;

    @Autowired
    StpInterfaceImpl stpInterface;

    @Autowired
    RoleMapper roleMapper;

    /**
     * 根据openid查找用户类型（等同查找用户存在）
     * <p>
     * 获取用户类型 == 判断是否为新用户
     * 不存在：获取类型失败 == 新用户
     * 存在：获取类型成功 == 注册用户
     *
     * @param openid openid
     * @return [user, worker] 或 null
     */
    @Deprecated
    public static String queryUserLoginType(String openid) {
        Jedis redis = RedisUtil.getRedis();
        redis.select(1);

        Set<String> keySet = loginType.keySet();
        for (String key : keySet) {
            String cachePath = loginType.get(key);
            long size = redis.llen(cachePath);
            for (int i = 0; i < Math.round((float) size / 2); i++) {
                if (redis.lindex(cachePath, i).equals(openid)) {
                    return key;
                }
                if (redis.lindex(cachePath, size - i - 1).equals(openid)) {
                    return key;
                }
            }
        }
        return null;
    }

    @GetMapping("/getUserRole")
    @ResponseBody
    public ResponseUtil getUserRole() {
        return ResponseUtil.setE(ResponseEnum.OK).setData(roleMapper.queryRoleIdAndRoleName());
    }

    // 盐值，建议与adminserver保持一致
    private static final String PASSWORD_SALT = "123456"; // 如需与adminserver一致请替换为实际值

    /**
     * 账号注册接口
     */
    @PostMapping("/register")
    public ResponseUtil register(@RequestBody Map<String, String> data) {
        String username = data.get("username");
        String password = data.get("password");
        String nickname = data.get("nickname");
        System.out.println("注册请求参数：" + data);
        UserEntity user = new UserEntity();
        user.setUsername(username);
        user.setPassword(DigestUtil.md5Hex(password + PASSWORD_SALT));
        user.setNickname(nickname != null ? nickname : username);
        user.setRegisterTime(new java.util.Date());
        user.setOpenid(UUID.randomUUID().toString().replaceAll("-", "")); // 生成唯一ID
        System.out.println("注册用户对象：" + user);
        boolean result = userService.save(user);
        System.out.println("save结果：" + result);
        // 注册成功后自动分配普通用户角色
        if (result) {
            // 动态查找"普通用户"角色ID
            RoleEntity userRoleEntityDb = roleMapper.selectOne(new QueryWrapper<RoleEntity>().eq("role_name", "普通用户"));
            if (userRoleEntityDb != null) {
                UserRoleEntity userRole = new UserRoleEntity();
                userRole.setUserId(user.getOpenid());
                userRole.setRoleId(userRoleEntityDb.getRoleId());
                userRole.setEnabled(true);
                userRoleMapper.insert(userRole);
            } else {
                System.err.println("未找到'普通用户'角色，请检查role表数据");
            }
        }
        return ResponseUtil.setE(ResponseEnum.OK).setMsg("注册成功");
    }

    /**
     * 账号密码登录接口
     */
    @PostMapping("/login")
    public ResponseUtil loginByUsername(@RequestBody Map<String, String> data) {
        String username = data.get("username");
        String password = data.get("password");
        String requestedRole = data.get("userType"); // 获取用户请求的角色类型
        
        if (username == null || password == null) {
            return ResponseUtil.setE(ResponseEnum.PARAMS_ERROR).setMsg("用户名或密码不能为空");
        }
        
        // 1. 检查是否是维修工邀请码登录
        redis.select(0); // 确保在正确的Redis数据库
        String workerInfoJson = redis.get(ADD_WORKER_PREFIX + password);
        if (workerInfoJson != null) {
            try {
                // 解析维修工信息
                WorkerEntity workerInfo = JSON.parseObject(workerInfoJson, WorkerEntity.class);
                
                // 验证手机号是否匹配
                if (workerInfo.getWorkerPhone() != null && workerInfo.getWorkerPhone().equals(username)) {
                    log.info("维修工邀请码登录: {}", username);
                    
                    // 创建维修工账号
                    UserEntity newWorker = new UserEntity();
                    newWorker.setUsername(username);
                    newWorker.setPassword(DigestUtil.md5Hex(password + PASSWORD_SALT)); // 使用邀请码作为初始密码
                    newWorker.setNickname(workerInfo.getWorkerName());
                    newWorker.setRegisterTime(new java.util.Date());
                    
                    // 生成短一点的唯一ID (确保不超过30字符) - 这个ID需要同时作为user表和worker表的openid
                    String openid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 30);
                    log.info("生成维修工openid: {}", openid);
                    newWorker.setOpenid(openid);
                    
                    // 更新WorkerEntity的openid
                    workerInfo.setOpenid(openid); // 使用相同的openid
                    
                    // 保存用户
                    userService.save(newWorker);
                    
                    // 查找维修员角色ID
                    RoleEntity workerRoleEntityDb = roleMapper.selectOne(new QueryWrapper<RoleEntity>().eq("role_name", "维修员"));
                    if (workerRoleEntityDb == null) {
                        log.error("未找到'维修员'角色，请检查role表数据");
                        return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("系统错误：未找到维修员角色");
                    }
                    
                    log.info("找到维修员角色: {}", workerRoleEntityDb.getRoleName());
                    
                    // 分配维修工角色
                    UserRoleEntity userRole = new UserRoleEntity();
                    userRole.setUserId(openid);
                    userRole.setRoleId(workerRoleEntityDb.getRoleId());
                    userRole.setEnabled(true);
                    userRoleMapper.insert(userRole);
                    
                    // 同时保存到worker表
                    workerInfo.setRegisterTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                    workerService.save(workerInfo);
                    log.info("保存维修工信息到worker表: {}", workerInfo);
                    
                    // 登录并生成token
                    StpUtil.login(openid);
                    SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                    
                    // 删除Redis中的邀请码
                    redis.del(ADD_WORKER_PREFIX + password);
                    
                    // 返回token和用户信息
                    Map<String, Object> result = new HashMap<>();
                    result.put(tokenInfo.getTokenName(), tokenInfo.getTokenValue());
                    result.put("username", newWorker.getUsername());
                    result.put("nickname", newWorker.getNickname());
                    result.put("loginType", "worker"); // 明确设置为worker类型
                    
                    // 如果用户请求的角色类型与实际类型不一致，返回提示信息
                    if (requestedRole != null && !requestedRole.equals("worker")) {
                        result.put("roleMessage", "您选择的角色类型与实际不符，您的实际身份是维修工");
                    }
                    
                    return ResponseUtil.setE(ResponseEnum.LOGIN_SUCCESS).setData(result);
                }
            } catch (Exception e) {
                log.error("维修工邀请码登录处理异常", e);
            }
        }
        
        // 2. 常规用户登录逻辑
        UserEntity user = userService.getByUsername(username);
        if (user == null) {
            return ResponseUtil.setE(ResponseEnum.LOGIN_INFO_ERROR).setMsg("用户不存在");
        }
        String encrypted = DigestUtil.md5Hex(password + PASSWORD_SALT);
        if (!encrypted.equals(user.getPassword())) {
            return ResponseUtil.setE(ResponseEnum.LOGIN_INFO_ERROR).setMsg("密码错误");
        }
        
        // 登录并生成token
        StpUtil.login(user.getOpenid());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        
        // 查询用户角色
        UserRolePermissionEntity rolePermission = userRoleMapper.queryUserRoleByUserId(user.getOpenid());
        log.info("用户角色信息: {}", rolePermission);
        
        // 判断用户类型
        String userType = "user";
        if (rolePermission != null && rolePermission.getRoleName() != null) {
            if ("维修员".equals(rolePermission.getRoleName())) {
                userType = "worker";
            }
        }
        
        // 返回token和用户信息
        Map<String, Object> result = new HashMap<>();
        result.put(tokenInfo.getTokenName(), tokenInfo.getTokenValue());
        result.put("username", user.getUsername());
        result.put("nickname", user.getNickname());
        result.put("loginType", userType);
        
        // 如果用户请求的角色类型与实际类型不一致，返回提示信息
        if (requestedRole != null && !requestedRole.equals(userType)) {
            result.put("roleMessage", "您选择的角色类型与实际不符，您的实际身份是" + 
                    (userType.equals("worker") ? "维修工" : "普通用户"));
        }
        
        return ResponseUtil.setE(ResponseEnum.LOGIN_SUCCESS).setData(result);
    }

    /**
     * 需要登录才能访问的接口示例
     */
    @SaCheckLogin
    @GetMapping("/profile")
    public ResponseUtil getProfile() {
        String userId = (String) StpUtil.getLoginId();
        UserEntity user = userService.getById(userId);
        if (user == null) {
            return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("用户不存在");
        }
        Map<String, Object> profile = new HashMap<>();
        profile.put("username", user.getUsername());
        profile.put("nickname", user.getNickname());
        profile.put("registerTime", user.getRegisterTime());
        return ResponseUtil.setE(ResponseEnum.OK).setData(profile);
    }
}
